package com.gilight.base.aspect;

import com.alibaba.fastjson.JSONObject;
import com.gilight.base.aspect.annotation.OperatorLog;
import com.gilight.base.base.LoginUserInfo;
import com.gilight.base.model.SysOperatorLog;
import com.gilight.base.model.SysUser;
import com.gilight.base.service.SysOperatorLogService;
import com.gilight.base.service.UserService;
import com.gilight.base.util.IPUtils;
import com.gilight.base.util.ShiroUtil;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * @author xuhs
 * @description 操作日志切面
 * @date 2019/10/17
 */
@Aspect
@Component
public class OperatorLogAspect {
    /**
     * 操作日志业务接口
     */
    @Autowired
    private SysOperatorLogService sysOperatorLogService;

    @Autowired
    private UserService userServiceImpl;

    /**
     * 定义
     */
    @Pointcut("@annotation(com.gilight.base.aspect.annotation.OperatorLog)")
    public void logPointCut() {
    }

    /**
     * 切面逻辑处理
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        saveSysOperatorLog(point,time);
        return result;
    }

    /**
     * 持久化操作日志
     * @param joinPoint 切点
     * @param time 时长
     */
    private void saveSysOperatorLog(ProceedingJoinPoint joinPoint, long time) {
        try{
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SysOperatorLog log = new SysOperatorLog();
            OperatorLog logAnno = method.getAnnotation(OperatorLog.class);
            //设置操作日志内容
            if(logAnno != null){
                log.setLogContent(logAnno.value());
            }
            //请求的方法名
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = signature.getName();
            log.setMethod(className + "." + methodName + "()");

            //设置操作类型
            log.setOperateType(logAnno.operateType());

            //请求的参数
            Object[] args = joinPoint.getArgs();
            String params = JSONObject.toJSONString(args);
            log.setRequestParam(params);
            //获取request
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            // 设置请求URL地址
            log.setRequestUrl(request.getRequestURI());
            // 设置请求类型：POST、GET
            log.setRequestType(request.getMethod());
            //设置IP地址
            log.setIp(IPUtils.getIpAddr(request));
            //获取登录用户信息
            SysUser sysUser = ShiroUtil.getJWTUser();
            if(sysUser!=null){
                log.setRealName(sysUser.getUserName());
                log.setUserName(sysUser.getUserCode());
            }
            //耗时
            log.setCostTime(time);
            // 持久化进数据库
            sysOperatorLogService.add(log);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
